import logging
from typing import Annotated, List, Optional

from fastapi import APIRouter, Body, Depends, Path, Query, Request

from app.api.deps import CurrentUserDep, MenuServiceDep, require_permission
from app.core import settings
from app.exceptions.base import AppException
from app.models.system import SysUser
from app.schemas.base import Response
from app.schemas.menu import MenuForm, MenuVO, RouteVO
from app.schemas.option import IntOption
from app.utils.log_api_call import log

logger = logging.getLogger(__name__)

router = APIRouter(prefix=f"{settings.API_V1_STR}/menus", tags=["04.菜单接口"])


@router.get("", response_model=Response[List[MenuVO]], summary="菜单列表", description="查询菜单列表（支持条件过滤）")
@log(content="菜单列表", module="菜单")
async def get_menus(
    request: Request,
    current_user: CurrentUserDep,
    menu_service: MenuServiceDep,
    keyword: Optional[str] = Query(None, description="关键字"),
) -> Response[List[MenuVO]]:
    """
    菜单列表
    """
    try:
        menus = await menu_service.get_menus(keyword=keyword)
        return Response.success(data=menus)
    except Exception as e:
        raise AppException(message="获取菜单列表失败") from e


@router.get(
    "/options",
    response_model=Response[List[IntOption]],
    response_model_exclude_none=True,
    summary="菜单下拉列表",
    description="获取菜单下拉选项，可选仅返回父级菜单",
)
async def get_menu_options(
    current_user: CurrentUserDep,
    menu_service: MenuServiceDep,
    only_parent: bool = Query(description="是否只查询父级菜单", alias="onlyParent", default=False),
) -> Response[List[IntOption]]:
    """
    菜单下拉列表
    """
    try:
        rs = await menu_service.get_menu_options(only_parent=only_parent)
        return Response.success(data=rs)
    except Exception as e:
        raise AppException(message="获取菜单下拉列表失败") from e


@router.get(
    "/routes",
    response_model=Response[List[RouteVO]],
    response_model_exclude_none=True,
    summary="当前用户菜单路由列表",
    description="获取当前登录用户有权限访问的前端路由列表",
)
async def get_current_user_routes(
    current_user: CurrentUserDep, menu_service: MenuServiceDep
) -> Response[List[RouteVO]]:
    """
    当前用户菜单路由列表
    """
    try:
        roles = [role.code for role in current_user.roles]
        if not roles:
            return Response.success(data=[])

        is_root = settings.ADMIN_ROLE_CODE in roles

        rs = await menu_service.get_routes(role_codes=roles, is_root=is_root)
        return Response.success(data=rs)
    except Exception as e:
        raise AppException(message="获取当前用户菜单路由列表失败") from e


@router.get(
    "/{id}/form",
    response_model=Response[MenuForm],
    summary="菜单表单数据",
    description="根据菜单ID获取编辑表单数据，需 sys:menu:edit 权限",
)
@log(content="菜单表单数据", module="菜单")
async def get_menu_form(
    request: Request,
    current_user: Annotated[SysUser, Depends(require_permission("sys:menu:edit"))],
    menu_service: MenuServiceDep,
    id: int = Path(..., description="菜单ID"),
) -> Response[MenuForm]:
    """
    菜单表单数据
    """
    try:
        menu_form = await menu_service.get_menu_form(menu_id=id)
        return Response.success(data=menu_form)
    except Exception as e:
        raise AppException(message="获取菜单表单数据失败") from e


@router.post("", response_model=Response[None], summary="新增菜单", description="创建新菜单，需 sys:menu:add 权限")
@log(content="新增菜单", module="菜单")
async def add_menu(
    request: Request,
    menu_service: MenuServiceDep,
    current_user: Annotated[SysUser, Depends(require_permission("sys:menu:add"))],
    menu_form: MenuForm = Body(..., description="菜单表单数据"),
) -> Response[None]:
    """
    新增菜单
    """
    try:
        await menu_service.save_menu(menu_form=menu_form)
        return Response.success()
    except Exception as e:
        raise AppException(message="新增菜单失败") from e


@router.put(
    "/{id}", response_model=Response[None], summary="修改菜单", description="更新菜单信息，需 sys:menu:edit 权限"
)
@log(content="修改菜单", module="菜单")
async def update_menu(
    request: Request,
    menu_service: MenuServiceDep,
    current_user: Annotated[SysUser, Depends(require_permission("sys:menu:edit"))],
    menu_form: MenuForm = Body(..., description="菜单表单数据"),
) -> Response[None]:
    """
    修改菜单
    """
    try:
        await menu_service.save_menu(menu_form=menu_form)
        return Response.success()
    except Exception as e:
        raise AppException(message="修改菜单失败") from e


@router.delete(
    "/{id}", response_model=Response[None], summary="删除菜单", description="删除指定菜单，需 sys:menu:delete 权限"
)
@log(content="删除菜单", module="菜单")
async def delete_menu(
    request: Request,
    menu_service: MenuServiceDep,
    current_user: Annotated[SysUser, Depends(require_permission("sys:menu:delete"))],
    id: int = Path(..., description="菜单ID，多个以英文(,)分割"),
) -> Response[None]:
    """
    删除菜单
    """
    try:
        flag = await menu_service.delete_menu(menu_id=id)
        if flag:
            return Response.success()
        else:
            return Response.failed(msg="删除菜单失败")
    except Exception as e:
        raise AppException(message="删除菜单失败") from e


@router.patch(
    "/{menu_id}",
    response_model=Response[None],
    summary="修改菜单显示状态",
    description="控制菜单在前端是否显示，需 sys:menu:edit 权限",
)
@log(content="修改菜单显示状态", module="菜单")
async def update_menu_visible(
    request: Request,
    menu_service: MenuServiceDep,
    current_user: Annotated[SysUser, Depends(require_permission("sys:menu:edit"))],
    menu_id: int = Path(..., description="菜单ID"),
    visible: Optional[int] = Body(description="显示状态(1:显示;0:隐藏)"),
) -> Response[None]:
    """
    修改菜单显示状态
    """
    try:
        await menu_service.update_menu_visible(menu_id=menu_id, visible=visible)
        return Response.success()
    except Exception as e:
        raise AppException(message="修改菜单显示状态失败") from e
